package com.open.chat.server.controller;

import java.io.File;
import java.io.IOException;

import org.jim.core.ImChannelContext;
import org.jim.core.ImPacket;
import org.jim.core.packets.ChatBody;
import org.jim.core.packets.ChatType;
import org.jim.core.packets.Command;
import org.jim.core.packets.FileInfo;
import org.jim.core.packets.MsgType;
import org.jim.server.JimServerAPI;
import org.jim.server.command.CommandManager;
import org.jim.server.command.handler.ChatReqHandler;
import org.jim.server.protocol.ProtocolManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.open.chat.server.common.Common;
import com.open.chat.server.common.redis.CommonKey;
import com.open.chat.server.pojo.MyFileInfo;
import com.open.chat.server.utils.ChannelContextList;
import com.open.chat.server.utils.msg.Msg;
import com.open.chat.server.utils.msg.Status;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 上传文件替代版
 * @author admin
 *
 */
@RestController
@RequestMapping(value="/api/chat")
public class UploadController {
	@Value("${app.files.root}")
	private String root;
	@Value("${app.files.basis}")
	private String basis;
	
	/**
	 * 
	 * @param chatBody   from to(或groupId)  msgType chatType  
	 * @param file
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/uploadToChat")
	public Msg uploadToChat(MyFileInfo info, MultipartFile file) throws Exception {
		Msg msg = Msg.error();
		//获取用户的信息
		String fromUserId =  info.getFrom();
		if(StrUtil.isNotBlank(fromUserId)) {
			//从缓存去查询是否有该数据
			String key = CommonKey.getUserChannel(fromUserId);
//			ImSessionContext imSessionContext = channelContext.getSessionContext();
//			User clientUser = imSessionContext.getImClientNode().getUser();
			
			ImChannelContext channelContext = ChannelContextList.channel.get(key);
			if(channelContext == null) {
				return msg.setMsg("上传文件失败，通道不存在");
			}
			if(file == null) {
				return msg.setMsg("上传不存在");
			}
			//上传时的原文件名
			String fileName = file.getOriginalFilename();
			//拓展名
			String extentionName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
			
			if(isValid(extentionName, ".gif",".jpg",".jpeg",".bmp",".png")) {
				info.setMsgType(MsgType.MSG_TYPE_IMG.getNumber());
			}else{
				info.setMsgType(MsgType.MSG_TYPE_FILE.getNumber());
			}
			
			FileInfo fileInfo = new FileInfo();
			//上传文件
			String fileUrl = uploadFile(fromUserId, extentionName, file,fileInfo);
			
			if(fileUrl == null) {
				return msg.setMsg("上传文件失败");
			}
			
			fileInfo.setFileName(fileName);
			fileInfo.setFileUrl(fileUrl);
			
			//发送数据包直接到聊天
			ChatBody.Builder builder = 
					ChatBody.newBuilder()
					.setCmd(Command.COMMAND_CHAT_REQ.getNumber())
					.from(info.getFrom())
					//.to(info.getTo())
					.setCreateTime(DateUtil.current())
					.chatType(info.getChatType())
					.msgType(info.getMsgType())
					.fileInfo(fileInfo)
					;
			
			if(ChatType.CHAT_TYPE_PUBLIC.getNumber() == info.getChatType()){
				builder.groupId(info.getTo());
			}
			if(ChatType.CHAT_TYPE_PRIVATE.getNumber() == info.getChatType()){
				builder.to(info.getTo());
			}
			ChatBody body = builder.build();
			//作者WsConvertPacket中设置了setWsOpcode(Opcode.TEXT)，不方便改这部分代码
			//而且reqPacket还没写，给补充写了
			//发送数据包
			ImPacket packet = ProtocolManager.Converter.reqPacket(body.toByte(), Command.COMMAND_FILE_REQ, channelContext);
			ChatReqHandler chatReqHandler = CommandManager.getCommand(Command.COMMAND_CHAT_REQ,ChatReqHandler.class);
			//给目标发送聊天内容，自身需要响应结果（发送目标会发送多通道的）
			ImPacket resp = chatReqHandler.handler(packet, channelContext);
			//私聊发送，自身需要反馈
//			if(ChatType.CHAT_TYPE_PRIVATE.getNumber() == body.getChatType()) {
//				resp.setBody(body.toByte());
//				if(ObjectUtil.isNotNull(resp)){
//					JimServerAPI.sendToUser(body.getFrom(), resp);
//				}
//			}
			
			return msg.setCode(Status.CODE_OK);
			
		}
		
		
		
		return msg;
	}
	
	/**
	 * 上传文件
	 * @param userId 谁上传的
	 * @param file   文件
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/upload")
	public Msg upload(String userId,MultipartFile file) throws Exception {
		Msg msg = Msg.error();
		if(file == null) {
			return msg.setMsg("上传不存在");
		}
		//上传时的原文件名
		String fileName = file.getOriginalFilename();
		//拓展名
		String extentionName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
		
		FileInfo fileInfo = new FileInfo();
		//上传文件
		String fileUrl = uploadFile(userId, extentionName, file,fileInfo);
		
		if(fileUrl == null) {
			return msg.setMsg("上传文件失败");
		}
		fileInfo.setFileName(fileName);
		fileInfo.setFileUrl(fileUrl);
		
		return msg.setCode(Status.CODE_OK).setResult(fileInfo);
	}
	
	/**
	 * 上传组头像
	 * @param userId 谁上传的
	 * @param file   文件
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/uploadGroupAvatar")
	public Msg uploadGroupAvatar(String groupId,MultipartFile file) throws Exception {
		Msg msg = Msg.error();
		if(file == null) {
			return msg.setMsg("上传不存在");
		}
		//上传时的原文件名
		String fileName = file.getOriginalFilename();
		//拓展名
		String extentionName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
		
		FileInfo fileInfo = new FileInfo();
		//上传文件
		String fileUrl = uploadFile(groupId, extentionName, file,fileInfo);
		
		if(fileUrl == null) {
			return msg.setMsg("上传文件失败");
		}
		fileInfo.setFileName(fileName);
		fileInfo.setFileUrl(fileUrl);
		
		return msg.setCode(Status.CODE_OK).setResult(fileInfo);
	}
	/**
	 * 上传个人头像
	 * @param userId 谁上传的
	 * @param file   文件
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/uploadPersonAvatar")
	public Msg uploadPersonAvatar(String userId,MultipartFile file) throws Exception {
		Msg msg = Msg.error();
		if(file == null) {
			return msg.setMsg("上传不存在");
		}
		//上传时的原文件名
		String fileName = file.getOriginalFilename();
		//拓展名
		String extentionName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
		
		FileInfo fileInfo = new FileInfo();
		//上传文件
		String fileUrl = uploadFile(userId, extentionName, file,fileInfo);
		
		if(fileUrl == null) {
			return msg.setMsg("上传文件失败");
		}
		fileInfo.setFileName(fileName);
		fileInfo.setFileUrl(fileUrl);
		
		return msg.setCode(Status.CODE_OK).setResult(fileInfo);
	}
	/**
	 *  上传文件
	 * @param file
	 * @return
	 */
	private String uploadFile(String from ,String extentionName,MultipartFile file,FileInfo info) {
		//处理上传地址  
		StringBuilder filePath = new StringBuilder();
		filePath.append(root).append(basis).append(Common.SEPARATOR)
			.append(from).append(Common.SEPARATOR)
			.append(IdUtil.simpleUUID()).append(extentionName);
			
		String  httpPath =  filePath.substring(root.length());
		//.writeByteArrayToFile(file, uploadFile.getData());
		File f;
		try {
			f = FileUtil.writeBytes(file.getBytes(), filePath.toString());
			if(f.exists()) {
				info.setFileSize(f.length());
				return httpPath;
			}
		} catch (IORuntimeException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
		
	}
	
	private boolean isValid(String type, String... allowTypes) {
		if (null == type || "".equals(type.trim())) {
			return false;
		}
		for (String t : allowTypes) {
			if (type.equals(t)) {
				return true;
			}
		}
		return false;
	}
}

